/**
 * This is the file defined the dataset api. It contains the define of the record, the metadata
 *  and the dataset.
 *
 * @since 1/5/2008
 * @author Jack
 */
dojo.provide("spaghetti.dataset.api");

dojo.require("spaghetti.utility");
dojo.require("spaghetti.dataset.api.metadata");
dojo.require("spaghetti.dataset.api.cursor");

//---------------------------------------
// Interfaces define.

//=======================================
// For record.

dojo.declare("spaghetti.dataset.api.Record", null, {
    //	summary:
    //		This is the record mixin for data object. Every record must be attached to a dataset.
    //		Because data object can be anything(xml node, javascript object, remote object, etc). 
    //		So the record mixin doesn't has the ability to read or write its property. The dataset
    //		has the ability, and this design grant dataset the ability to track every change in the
    //		record. Every record out of dataset, must mixin this record mixin.
    
    /*Object*/
    get: function(/*String*/property){
        //	summary:
        //		Get the property in this record. The property can be anything.
        //
        //	property:
        //		The property name
        
        // Let the dataset to get the property.
        return this.dataset.getProperty(this, property);
    },
    
    set: function(/*String*/property, /*Object*/ value){
        //	summary:
        //		Set the property of this record. The record can fire a onChange event.
        //
        //	property:
        //		The property name.
        //
        //	value:
        //		The property value.
        
        // If the property name is null. Ignore it.
        if (spaghetti.isNull(property)) 
            return;
        
        // Fetch the old value.
        var oldValue = this.get(property);
        
        // Let the dataset to set the property.
        this.dataset.setProperty(this, property, value);
        
        // Fire the onChange event.
        this.onChange(property, oldValue, value);
    },
    
    /*String[]*/
    getPropertyNames: function(){
        //	summary:
        //		Get all the property names in this record.
        
        // Leave the work for dataset, of course, dataset can use its metadata
        // to implement this.
        return this.dataset.getPropertyNames(this);
    },
    
    onChange: function(/*String*/property, /*Object*/ oldValue, /*Object*/ newValue){
        //	summary:
        //		The onChange event for this record. It fires when the property of this
        //		record changed.
    }
});

//=======================================
// For Dataset.

dojo.declare("spaghetti.dataset.api", spaghetti.dataset.api.Metadata, {
    //	summary:
    //		The dataset api. The dataset is an array of recrods. The record can be find by index.
    
    isRecord: function(/*Record*/record){
        //	summary:
        //		If the record is a valid record in this dataset.
        
        spaghetti.notImplement("isRecord");
    },
    
    /*Record*/
    getRecord: function(/*Number*/index){
        //	summary:
        //		Get the record by index. 
        //
        //	index: Integer
        //		The index of the record.
        
        spaghetti.notImplement("getRecord");
    },
    
    addRecord: function(/*Object*/data, /*Number*/ index){
        //	summary:
        //		Add a record. Note that the record is create by the dataset from your data.
        //		The data must follow some structure that defined by the dataset. Different
        //		dataset, different data structure.
        //	
        //	data:
        //		The data that to create record.
        //	
        //	index:
        //		The index of the new record. If index is undefined, push the new record at the bottom.
        
        spaghetti.notImplement("addRecord");
    },
    
    removeRecord: function(/*Record*/record){
        //	summary:
        //		Remove the record, by it or by its index.
        
        spaghetti.notImplement("removeRecord");
    },
    
    /*Object*/
    getProperty: function(/*Record*/record, /*String*/ property){
        //	summary:
        //		Get the property of the record. The interface function for different implementations.
        //
        //	record: Record
        //		The record.
        //
        //	property: String
        //		The property name.
        
        spaghetti.notImplement("getProperty");
    },
    
    setProperty: function(/*Record*/record, /*String*/ property, /*Object*/ value)/*Throws ValidationException*/{
        //	sumamry:
        //		Set the property of the record. Same as the getProperty. If the record's property has
        //		validator, use the validator to validate the value. 
        //
        //	throws: ValidationException
        //		If failed to validate, throw this exception.
        
        spaghetti.notImplement("setProperty");
    },
    
    /*Number*/
    indexOfRecord: function(/*Record*/record){
        //	summary:
        //		Return the index of the record. If the record is not a validate record of this dataset,
        //		return -1
        
        spaghetti.notImplement("containsRecord");
    },
    
    /*Number*/
    getRecordCount: function(){
        //	summary:
        //		Return the record count of this dataset.
        
        spaghetti.notImplement("getRecordCount");
    },
    
    /*Cursor*/
    query: function(/*Object || null*/query){
        //	summary:
        //		Query in this dataset.  Mostly is the criteria of the record. Or constraints. 
        //	
        //	example:
        //	|	{ age : 26, name : "Jack"} or { begin : 10, end : 20, filter : funciton(index){ return index % 2; } } 
        //	|	or { index : 10 }. 
        //		The query return a cursor of the resultset. If the query is null, the resultset 
        //		is all the records in this dataset. Begin with index 0.
        
        spaghetti.notImplement("query");
    },
    
    /*Boolean*/
    isDirty: function(){
        //	summary:
        //		Return true f the data in this dataset changed.
        
        spaghetti.notImplement("isDirty");
    },
    
    //---------------------------------------------
    // Events
    onRecordAdd: function(/*Record*/record, /*Number*/ index){
        //	summary:
        //		Fire when a record is inserted into this dataset.
        //
        //	record: Record
        //		The record added.
        //
        //	index: Integer
        //		The index of the new record.
    },
    
    onRecordChange: function(/*Record*/record, /*String*/ property, /*Object*/ oldValue, /*Object*/ newValue){
        //	summary:
        //		Fire when a record in this dataset is changeed.
        //
        //	record: Record
        //		The changed record.
        //
        //	property: String
        //		The property name.
        //
        //	oldValue: Object
        //		The old value for the property.
        //
        //	newValue: Object
        //		The new value for the property.
    },
    
    onRecordRemove: function(/*Record*/record){
        //	summary:
        //		Fire when a record in this dataset is removed.
    }
});
